/*!
 * \file ISelStraCtx.h
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 *
 * \brief 选股策略上下文接口定义
 * 
 * \details 该文件定义了SEL（Stock Selection）策略的核心接口。
 *          选股策略是一种用于股票选择和组合管理的中长期策略，主要特点包括：
 *          - 基于基本面或技术分析进行股票筛选
 *          - 支持股票池管理和动态调仓
 *          - 适用于股票、ETF等权益类品种
 *          - 支持多因子模型和量化选股
 *          该接口提供了选股策略所需的全部功能，包括：
 *          - 股票数据获取和分析
 *          - 持仓管理和调仓操作
 *          - 定时调度和信号触发
 *          - 历史数据回测和实盘交易
 */
#pragma once
#include <stdint.h>
#include <functional>
#include "../Includes/WTSMarcos.h"

NS_WTP_BEGIN
class WTSCommodityInfo;
class WTSSessionInfo;
class WTSTickData;
struct WTSBarStruct;
class WTSKlineSlice;
class WTSTickSlice;

/*!
 * \typedef FuncEnumSelPositionCallBack
 * \brief 选股策略持仓枚举回调函数类型定义
 * 
 * \details 用于枚举选股策略持仓时的回调函数类型。
 *          第一个参数为股票代码，第二个参数为持仓数量（权重）。
 */
typedef std::function<void(const char*, double)> FuncEnumSelPositionCallBack;

/*!
 * \class ISelStraCtx
 * \brief 选股策略上下文接口
 * 
 * \details 这是SEL（Stock Selection）策略的核心接口，定义了选股和组合管理所需的全部功能：
 * 
 * **主要功能模块：**
 * - **股票筛选**: 基于多种因子进行股票筛选和评分
 * - **组合管理**: 股票组合构建、权重分配和风险控制
 * - **调仓操作**: 定期或条件触发的组合调整
 * - **数据获取**: K线、Tick、基本面等数据接口
 * - **定时调度**: 支持按时间或事件触发策略逻辑
 * - **回测支持**: 完整的历史数据回测功能
 * 
 * **适用策略类型：**
 * - 量化选股策略
 * - 多因子选股模型
 * - Smart Beta策略
 * - 行业轮动策略
 * - 基本面量化策略
 * - ETF配对交易策略
 * 
 * **技术特点：**
 * - 支持A股、港股、美股等多市场
 * - 灵活的持仓权重管理
 * - 完善的风险控制机制
 * - 高效的数据访问接口
 * - 支持实时和定时两种调度模式
 * 
 * \note 该接口为纯虚接口，具体实现由SelStraContext类提供
 * \warning 选股策略涉及多品种操作，需要注意风险分散和资金管理
 * \see SelStraContext, SelStraBaseCtx
 */
class ISelStraCtx
{
public:
	/*!
	 * \brief 构造函数
	 * \param[in] name 策略名称
	 */
	ISelStraCtx(const char* name) :_name(name){}
	virtual ~ISelStraCtx(){}

	/*!
	 * \brief 获取策略名称
	 * \return 策略名称字符串
	 */
	inline const char* name() const{ return _name.c_str(); }

public:
	/*!
	 * \brief 获取策略ID
	 * \return 策略的唯一标识ID
	 */
	virtual uint32_t id() = 0;

	//回调函数
	/*!
	 * \brief 策略初始化回调
	 * 
	 * \details 策略启动时被调用，用于进行策略的初始化工作：
	 *          - 加载股票池和因子数据
	 *          - 初始化选股模型参数
	 *          - 设置调仓频率和风控参数
	 *          - 订阅需要的市场数据
	 * 
	 * \note 选股策略的初始化通常需要加载大量历史数据
	 * \warning 避免在初始化中进行耗时的计算操作
	 */
	virtual void on_init() = 0;
	
	/*!
	 * \brief 交易时段开始回调
	 * \param[in] uTDate 交易日期，格式为YYYYMMDD
	 * 
	 * \details 每个交易日开始时被调用：
	 *          - 更新股票池和基础数据
	 *          - 计算当日选股因子
	 *          - 检查是否需要调仓
	 */
	virtual void on_session_begin(uint32_t uTDate) = 0;
	
	/*!
	 * \brief 交易时段结束回调
	 * \param[in] uTDate 交易日期，格式为YYYYMMDD
	 * 
	 * \details 每个交易日结束时被调用：
	 *          - 计算当日收益和风险指标
	 *          - 保存策略状态和统计数据
	 *          - 准备下一交易日的数据
	 */
	virtual void on_session_end(uint32_t uTDate) = 0;
	
	/*!
	 * \brief Tick数据回调
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] newTick 最新的Tick数据
	 * \param[in] bEmitStrategy 是否触发策略逻辑，默认为true
	 * 
	 * \details 选股策略通常不需要高频的Tick数据，但可以用于：
	 *          - 实时监控持仓股票的价格变动
	 *          - 触发止损或止盈逻辑
	 *          - 计算实时的组合净值
	 */
	virtual void on_tick(const char* stdCode, WTSTickData* newTick, bool bEmitStrategy = true) = 0;
	
	/*!
	 * \brief K线数据回调
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] period 周期类型字符串
	 * \param[in] times 周期倍数
	 * \param[in] newBar 最新的K线数据
	 * 
	 * \details K线数据是选股策略的主要数据源：
	 *          - 计算技术指标和因子值
	 *          - 执行选股逻辑和信号判断
	 *          - 触发调仓和风控操作
	 */
	virtual void on_bar(const char* stdCode, const char* period, uint32_t times, WTSBarStruct* newBar) = 0;
	
	/*!
	 * \brief 定时调度回调
	 * \param[in] curDate 当前日期，格式为YYYYMMDD
	 * \param[in] curTime 当前时间，格式为HHMM
	 * \param[in] fireTime 触发时间，格式为HHMM
	 * \return 是否成功处理调度事件
	 * 
	 * \details 按预设时间触发的调度事件：
	 *          - 定期选股和调仓操作
	 *          - 风险检查和组合再平衡
	 *          - 业绩统计和报告生成
	 */
	virtual bool on_schedule(uint32_t curDate, uint32_t curTime, uint32_t fireTime) = 0;
	
	/*!
	 * \brief 回测结束回调
	 * 
	 * \details 仅在历史回测模式下，回测结束时被调用：
	 *          - 计算回测业绩指标
	 *          - 生成回测报告
	 *          - 输出选股效果统计
	 * 
	 * \note 该函数只在回测模式下才会被调用
	 */
	virtual void on_bactest_end() {};

	/*!
	 * \brief K线收盘回调
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] period 周期类型字符串
	 * \param[in] newBar 收盘K线数据
	 * 
	 * \details K线周期结束时被调用：
	 *          - 计算周期性技术指标
	 *          - 执行周期性选股逻辑
	 *          - 更新因子值和排名
	 */
	virtual void on_bar_close(const char* stdCode, const char* period, WTSBarStruct* newBar) = 0;
	
	/*!
	 * \brief Tick数据更新后回调
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] newTick 最新的Tick数据
	 * 
	 * \note 默认为空实现，策略可根据需要重写
	 */
	virtual void on_tick_updated(const char* stdCode, WTSTickData* newTick){}
	
	/*!
	 * \brief 策略定时调度回调
	 * \param[in] curDate 当前日期，格式为YYYYMMDD
	 * \param[in] curTime 当前时间，格式为HHMM
	 * 
	 * \details 策略自定义的定时调度事件：
	 *          - 用户自定义的调度逻辑
	 *          - 灵活的时间触发机制
	 * 
	 * \note 默认为空实现，策略可根据需要重写
	 */
	virtual void on_strategy_schedule(uint32_t curDate, uint32_t curTime) {}

	/*!
	 * \brief 枚举持仓回调
	 * \param[in] cb 持仓枚举回调函数
	 * 
	 * \details 遍历当前所有持仓，通过回调函数返回每个持仓的信息：
	 *          - 用于持仓统计和风险分析
	 *          - 支持组合优化和调仓决策
	 */
	virtual void enum_position(FuncEnumSelPositionCallBack cb) = 0;

	//交易接口
	/*!
	 * \brief 获取持仓数量
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] bOnlyValid 是否只返回有效持仓，默认为false
	 * \param[in] userTag 用户标签，用于区分不同用途的持仓，默认为空
	 * \return 持仓数量或权重
	 * 
	 * \details 获取指定股票的当前持仓：
	 *          - 可以是实际股数或权重比例
	 *          - 支持按用户标签分类管理
	 */
	virtual double stra_get_position(const char* stdCode, bool bOnlyValid = false, const char* userTag = "") = 0;
	
	/*!
	 * \brief 设置持仓数量
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] qty 目标持仓数量或权重
	 * \param[in] userTag 用户标签，用于区分不同用途的持仓，默认为空
	 * 
	 * \details 设置指定股票的目标持仓：
	 *          - 支持绝对数量或相对权重
	 *          - 自动计算所需的买卖操作
	 *          - 支持分批执行和风控检查
	 * 
	 * \note 这是选股策略的核心调仓接口
	 * \warning 需要考虑市场流动性和冲击成本
	 */
	virtual void stra_set_position(const char* stdCode, double qty, const char* userTag = "") = 0;

	/*!
	 * \brief 获取最新价格
	 * \param[in] stdCode 标准化合约代码
	 * \return 最新价格，如果没有数据则返回0
	 */
	virtual double stra_get_price(const char* stdCode) = 0;

	/*!
	 * \brief 获取当前日期
	 * \return 当前日期，格式为YYYYMMDD
	 */
	virtual uint32_t stra_get_date() = 0;
	
	/*!
	 * \brief 获取当前时间
	 * \return 当前时间，格式为HHMM
	 */
	virtual uint32_t stra_get_time() = 0;

	/*!
	 * \brief 获取品种信息
	 * \param[in] stdCode 标准化合约代码
	 * \return 品种信息对象指针
	 */
	virtual WTSCommodityInfo* stra_get_comminfo(const char* stdCode) = 0;
	
	/*!
	 * \brief 获取交易时段信息
	 * \param[in] stdCode 标准化合约代码
	 * \return 交易时段信息对象指针
	 */
	virtual WTSSessionInfo* stra_get_sessinfo(const char* stdCode) = 0;
	
	/*!
	 * \brief 获取K线数据
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] period 周期字符串，如"d1"、"w1"、"m1"等
	 * \param[in] count 获取的K线根数
	 * \return K线数据切片对象指针
	 * 
	 * \details 获取历史K线数据，是选股策略计算因子的主要数据源
	 */
	virtual WTSKlineSlice*	stra_get_bars(const char* stdCode, const char* period, uint32_t count) = 0;
	
	/*!
	 * \brief 获取Tick数据
	 * \param[in] stdCode 标准化合约代码
	 * \param[in] count 获取的Tick数量
	 * \return Tick数据切片对象指针
	 * 
	 * \details 选股策略一般较少使用Tick数据，主要用于精确的价格分析
	 */
	virtual WTSTickSlice*	stra_get_ticks(const char* stdCode, uint32_t count) = 0;
	
	/*!
	 * \brief 获取最新Tick数据
	 * \param[in] stdCode 标准化合约代码
	 * \return 最新的Tick数据对象指针
	 */
	virtual WTSTickData*	stra_get_last_tick(const char* stdCode) = 0;

	/*!
	 * \brief 订阅Tick数据
	 * \param[in] stdCode 标准化合约代码
	 * 
	 * \details 订阅指定股票的Tick数据推送，用于实时监控价格变动
	 */
	virtual void stra_sub_ticks(const char* stdCode) = 0;

	/*!
	 * \brief 输出信息日志
	 * \param[in] message 日志信息
	 */
	virtual void stra_log_info(const char* message) = 0;
	
	/*!
	 * \brief 输出调试日志
	 * \param[in] message 日志信息
	 */
	virtual void stra_log_debug(const char* message) = 0;
	
	/*!
	 * \brief 输出错误日志
	 * \param[in] message 日志信息
	 */
	virtual void stra_log_error(const char* message) = 0;

	/*!
	 * \brief 保存用户数据
	 * \param[in] key 数据键名
	 * \param[in] val 数据值
	 * 
	 * \details 保存策略的自定义数据，用于：
	 *          - 保存选股结果和因子值
	 *          - 存储策略状态和参数
	 *          - 记录调仓历史和业绩指标
	 * 
	 * \note 数据会持久化存储，重启后仍然有效
	 */
	virtual void stra_save_user_data(const char* key, const char* val){}

	/*!
	 * \brief 加载用户数据
	 * \param[in] key 数据键名
	 * \param[in] defVal 默认值，如果没有找到数据则返回该值
	 * \return 用户数据字符串
	 */
	virtual const char* stra_load_user_data(const char* key, const char* defVal = "") { return defVal; }

protected:
	std::string _name;	///< 策略名称
};

NS_WTP_END